#include <string>
#include <regex>
#include <iostream>
#include <algorithm>
#include <exception>

using namespace std;

void test1(string& data, regex& reg)
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    auto pos=data.cbegin();
    auto end=data.cend();
    smatch m;
    for(;regex_search(pos,end,m,reg);pos=m.suffix().first)
    {
        cout << "match: " << m.str() << endl;
        cout << "tag: " << m.str(1) << endl;
        cout << "value: " << m.str(2) << endl;
    }
}

void test2()
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    string test_string = "hello_ch30.bin";
    regex pattern("^.+_ch(\\d{1,3})\\.bin$");
    smatch match;
    if (regex_match(test_string, match, pattern))
    {
        cout << match.str()<<endl;
        cout << match.str(1)<<endl;
    }
}

void test3(string& data, regex& reg)
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    sregex_iterator pos(data.cbegin(), data.cend(), reg);
    sregex_iterator end;

    for(; pos != end; ++ pos)
    {
        cout << "match: " << pos->str() << endl;
        cout << "tag:   " << pos->str(1) << endl;
        cout << "value: " << pos->str(2) << endl;
    }

    sregex_iterator beg(data.cbegin(), data.cend(), reg);
    for_each(beg, end, [](const smatch& m) {
        cout << "match: " << m.str() << endl;
        cout << "tag:   " << m.str(1) << endl;
        cout << "value: " << m.str(2) << endl;
    });
}

void test4(string& data, regex& reg)
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    sregex_token_iterator pos(data.cbegin(), data.cend(), reg, {0,2});
    sregex_token_iterator end;
    for(; pos != end; ++ pos)
    {
        cout << "match: " << pos->str() << endl;
    }
    cout << endl;

    string names = "nico, jim, helmut, paul, tim, john paul, rita";
    regex sep("[ \t\n]*[,;.][ \t\n]*");
    sregex_token_iterator p(names.cbegin(), names.cend(), sep, -1);
    sregex_token_iterator e;
    for (; p != e; ++ p)
    {
        cout << "name:  " << *p << endl;
    }
}

void test5(string& data, regex& reg)
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    cout << regex_replace(data, reg, "<$1 value=\"$2\"/>") << endl;
    cout << regex_replace(data, reg, "<\\1 value=\"\\2\"/>", regex_constants::format_sed) << endl;
}

void test6(void)
{
    cout << "\n\n==============" << string(__func__ ) <<  "======================" << endl;
    try
    {
        regex pat("<(.*\\}>");
    }
    catch (const regex_error& e)
    {
        cerr << "regex_error: \n"
             << "  what(): " << e.what() << "\n"
             << "  code(): " << e.code() << endl;
    }

}

int main()
{
    string data = "<person>\n"
                "<first>Nico</first>\n"
                "<last>Josu</last>\n"
                "</person>\n";
    regex reg("<(.*)>(.*)</(\\1)>");

    test1(data, reg);
    test2();
    test3(data, reg);
    test4(data, reg);
    test5(data, reg);
    test6();
}
